package test.panel4;

import test.CPU.CPUController;
import test.CPU.CPUObserver;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Scheduler implements CPUObserver {
    Map<Integer, Process> runningProcess = Control.running_process;

    private static final Scheduler instance = new Scheduler();

    public static Scheduler getInstance(){return instance;}

    private Scheduler() {
        CPUController.addObserver(this);
    }

    // 先来先服务(FCFS)
    public Process getFCFS() {
        runningProcess = Control.running_process;
        return runningProcess.values()
                .stream()
                .filter(p -> !p.state.equals("完成"))
                .filter(p -> !p.state .equals("资源不足"))
                .min(Comparator.comparingInt(p -> p.pid))
                .orElse(null);
    }

    // 短作业优先(SJF)
    public Process getSJF() {
        runningProcess = Control.running_process;
        return runningProcess.values()
                .stream()
                .filter(p -> !p.state.equals("完成"))
                .filter(p -> !p.state .equals("资源不足"))
                .min(Comparator.comparingInt(p -> p.needTime))
                .orElse(null);
    }

    // 最早截止时间优先(EDF)
    public Process getEDF() {
        runningProcess = Control.running_process;
        // 添加 Process 类中的截止时间属性，例如：public int deadline;
        return runningProcess.values()
                .stream()
                .filter(p -> !p.state.equals("完成"))
                .filter(p -> !p.state .equals("资源不足"))
                .min(Comparator.comparingInt(p -> (CPUController.getInstance().getCpuClock() % p.period))) // Period here considered as deadline for illustration.
                .orElse(null);
    }

    // 最低松弛度优先(LSF)
    public Process getLSF() {
        runningProcess = Control.running_process;
        return runningProcess.values()
                .stream()
                .filter(p -> !p.state.equals("完成"))
                .filter(p -> !p.state .equals("资源不足"))
                .min(Comparator.comparingInt(p -> (p.period - (CPUController.getInstance().getCpuClock() % p.period) + p.workedTime - p.needTime)))
                .orElse(null);
    }

    public Process scheduleProcess(String scheduler) {
        return switch (scheduler.toUpperCase()) {
            case "先来先服务(FCFS)" -> getFCFS();
            case "短作业优先(SJF)" -> getSJF();
            case "最早截止时间优先(EDF)" -> getEDF();
            case "最低松弛度优先(LSF)" -> getLSF();
            default -> null;
        };
    }

    @Override
    public void CPUUpdate(int clock) {
        Process process = scheduleProcess(Control.scheduler);
        if(process == null){
            return;
        }
        Control.blockAllProcesses();
        process.setState("运行");
        process.run();
    }
}

